using System;
using System.Data;
using System.Globalization;

namespace BizElements.Core
{
	/// <summary>
	/// Data retrieved by stored procedure.
	/// </summary>
	/// <example>
	/// The following example uses generated stored procedure wrapper which returns StoredProcedureResult 
	/// that contains a DataTable with sales data for the given time interval.
	/// <code>
	/// public DataTable GetSalesStatisticForInterval(DateTime beginDate, DateTime endDate)
	/// {
	/// 	// Uses "Sales by Year" stored procedure to retrieve sales data for the given interval.
	/// 	StoredProcedureResult spResult = SP.SalesByYear(beginDate, endDate);
	/// 	return spResult.DataTable;
	/// }
	/// </code>
	/// </example>
    public sealed class StoredProcedureResult
	{
		#region Members.

        // Data retrieved by the stored procedure.
		DataSet resultSet;		
		
		// Value returned by the stored procedure. For SQL Server this is always integer or null, but other DBMSs support other types as well.
		object returnObject;

        // Value converted from returnObject. Caches value created by ReturnValue getter. Zero is default.
        int? returnedInteger;

		#endregion

		#region Constructors.

		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="resultSet">Data retrieved by stored procedure.</param>
		/// <param name="returnObj">Value returned by the stored procedure.</param>
		public StoredProcedureResult(DataSet resultSet, object returnObj)
		{
			this.resultSet = resultSet;
            this.returnObject = returnObj;
		}

		#endregion

		#region Properties.

		/// <summary>
		/// Gets the first <see cref="System.Data.DataTable"/> retrieved by the stored procedure. 
		/// <b>Null</b> if no DataTables have been retrieved.
		/// </summary>
		public DataTable DataTable
		{
			get			
			{
				if (this.resultSet != null  &&  this.resultSet.Tables.Count > 0)
					return this.resultSet.Tables[0];
				else
					return null;
			}
		}

		/// <summary>
		/// Gets the <see cref="System.Data.DataSet"/> retrieved by the stored procedure.
		/// May contain multiple DataTable objects.
		/// </summary>
		public DataSet DataSet
		{
			get {return this.resultSet;}
		}

		/// <summary>
		/// Gets the value returned by the stored procedure.
		/// </summary>
		public object ReturnObject
		{
			get {return this.returnObject;}
		}

		/// <summary>
		/// Gets the value returned by the stored procedure.
		/// Zero if stored procedure didn't return anything or if the procedure's return value is not an integer.
		/// </summary>
		public int ReturnValue
		{
			get
			{
                if (this.returnedInteger == null)
                    this.returnedInteger = TryConvertToInt(this.returnObject);

                return this.returnedInteger.Value;
			}
		}

        private static int TryConvertToInt(object val)
        {
            try 
            {
                if (val == null || val == DBNull.Value)
                    return 0;
                else
                    return Convert.ToInt32(val); 
            }
            catch 
            { 
                return 0; 
            }
        }

		#endregion
	}
}
